<template>
   <div
      class="lg-image"
      v-bind="$attrs"
      :style="`${width ? ('width:' + conversion(width) + ';') : ''}${height ? ('height:' + conversion(height) + ';') : ''}${previewSrcList && previewSrcList.length && newImgSrc ? 'cursor:pointer' : 'cursor: not-allowed'}`"
    >
        <!-- 预览 -->
        <img
            v-if="newImgSrc"
            :src="newImgSrc"
            :alt="alt"
            :loading="lazy && 'lazy' || 'eager'"
            :style="`${fit ? `object-fit: ${fit};`: ''}`"
            :referrerPolicy="referrerPolicy && 'no-referrer'"
            class="lg-image__inner"
            @load="onCallBack('load')"
            @error="onCallBack('error')"
            @click="onViewer(index)"
        >
        <span v-else class="lg-image__notimg">
          <i>Image</i>
          <i>加载失败</i>
        </span>
        <i
          v-if="isDelete && newImgSrc"
          class="lg-image--delete iconfont icon-close"
          :style="getDeleteStyle"
          @click="onCallBack('delete')"
        />
        <viewer
            v-if="imgList.length"
            :images="imgList"
            @inited="inited"
            class="lg-image__inner"
            :style="src && 'display:none'"
        >
            <img
                v-for="(item,index) in imgList"
                :key="`viewer-${index}`"
                :src="item"
                class="lg-image__inner"
                :style="`${fit ? `object-fit: ${fit};`: ''}`"
            >
        </viewer>
   </div>
</template>

<script>
// 非npm包下使用 先安装 npm install v-viewer -s
// 全局或局部引入
// import Viewer from 'v-viewer'
// import 'viewerjs/dist/viewer.css'
// Vue.use(Viewer)
import { deepClone, isObject, conversion } from '@/libs/index.js'
import { setTimeout } from 'timers'
export default {
  name: 'lgImage',
  props: {
    // 图片链接
    src: {
      type: String,
      default: ''
    },
    // 默认图链接
    defaultSrc: {
      type: String,
      default: ''
    },
    // 原生alt
    alt: {
      type: String,
      default: ''
    },
    // 确定图片如何适应容器框，同原生 object-fit
    fit: {
      type: String,
      default: ''
    },
    // 宽度
    width: {
      type: [Number, String],
      default: ''
    },
    // 高度
    height: {
      type: [Number, String],
      default: ''
    },
    // 删除图标size
    deleteParams: {
      type: Object,
      default: () => {
        return {
          fontSize: '18',
          color: '#000' // 可输入 #000  或rgba的前三位值 255,255,255
        }
      }
    },
    // 是否懒加载
    lazy: {
      type: Boolean,
      default: false
    },
    // 原生 referrerPolicy
    referrerPolicy: {
      type: Boolean,
      default: false
    },
    // 是否显示删除图标
    isDelete: {
      type: Boolean,
      default: false
    },
    // 图片预览的图片数据
    previewSrcList: {
      type: Array,
      default: () => { return [] }
    },
    // 图片预览列表对象URL所属的字段
    previewSrcListFile: {
      type: String,
      default: 'url'
    },
    // 图片预览组件的zIndex
    zIndex: {
      type: Number,
      default: 1000
    },
    index: {
      type: Number
    }
  },
  data () {
    return {
      imgList: [],
      newImgSrc: ''
    }
  },
  watch: {
    previewSrcList: {
      handler (newVal) {
        if (!newVal.length) return false
        if (typeof newVal[0] === 'string') {
          this.imgList = deepClone(newVal)
        } else if (isObject(newVal[0])) {
          let imgArr = []
          newVal.forEach(item => {
            if (item[this.previewSrcListFile]) {
              imgArr.push(item[this.previewSrcListFile])
            }
          })
          this.imgList = deepClone(imgArr)
        }
        this.$nextTick(() => {
          this.filtrationErrImage(newVal)
        })
      },
      deep: true,
      immediate: true
    },
    src: {
      handler (newVal) {
        this.newImgSrc = newVal
      },
      immediate: true
    }
  },
  computed: {
    getDeleteStyle () {
      let str = this.deleteParams.fontSize ? `font-size:${this.conversion(this.deleteParams.fontSize, true)};` : ''
      str += this.deleteParams.color ? `color:${this.conversionColor(this.deleteParams.color)};` : ''
      return str
    }
  },
  created() {
       this.getInitStatus() 
  },
  mounted () {
    this.filtrationErrImage(this.imgList)
  },
  methods: {
    // 判断有没有默认图，如果没有就直接返回，如果有,当图片不存在或破图片，使用默认图片显示
    getInitStatus (url) {
      let imgInstantiation = new Image()
      imgInstantiation.src = this.src
      setTimeout(() => {
        if (imgInstantiation.fileSize > 0 || (imgInstantiation.width > 0 && imgInstantiation.height > 0)) {
          this.newImgSrc = this.src
        } else {
          this.newImgSrc = this.defaultSrc || ''
        }
      }, 100)
    },
    promiseLoad(url) {
      return new Promise((resolve, reject) => {
        let imgInstantiation = new Image()
        imgInstantiation.src = url
        setTimeout(() => {
          if (imgInstantiation.fileSize > 0 || (imgInstantiation.width > 0 && imgInstantiation.height > 0)) {
            resolve(url)
          } else {
            resolve('')
          }
        }, 500)
      })
    },
    // 过滤错误预览图片
    filtrationErrImage(list) {
      let promiseAll = []
      let imgArr = []
      list.forEach(item => {
        let url = typeof item === 'string' ? item : item[this.previewSrcListFile]
        let fn = this.promiseLoad(url).then((res) => {
          if (res) {
            imgArr.push(res)
          }
        })
        promiseAll.push(fn)
      })
      Promise.all(promiseAll).then(result => {
        this.imgList = deepClone(imgArr)
      })
    },
    onViewer (index = 0, src) {
      if (!this.previewSrcList.length) return false
      this.$viewer.index = this.previewSrcList.length - 1 >= index ? index : this.getSrcIndex(src)
      this.$viewer.show()
    },
    getSrcIndex (src) {
      return this.imgList.findIndex(item => item == (src || this.src)) || 0
    },
    inited (viewer) {
      this.$viewer = viewer
      this.$viewer.options.zIndex = this.zIndex
    },
    // 有index返回index,没有返回src
    onCallBack (type) {
      let data = typeof this.index == 'number' ? this.index : this.src
      this.$emit(type, data)
    },
    conversion,
    conversionColor (val) {
      let status = val.indexOf('#') != -1
      return status ? val : `rgba(${val}, 1)`
    }
  }
}
</script>

<style lang="less" scoped>
.lg-image{
    position: relative;
    display: inline-block;
    overflow: hidden;
    width: 100%;
    height: 100%;
    .lg-image__notimg{
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction:column;
        align-items: center;
        justify-content: center;
        color: #fff;
        background: #dbdbdb;
        border-radius: 5px;
        letter-spacing: 1px;
        user-select: none;
        i{
          font-style: normal;
          line-height: 25px;
          font-size: 14px;
        }
    }
    .lg-image__inner{
        display: block;
        width: 100%;
        height: 100%;
        border-radius: 5px;
        object-fit: cover;
    }
    .lg-image--delete{
        cursor: pointer;
        user-select: none;
        position: absolute;
        right: 0;
        top: 0;
    }
}
</style>
